package com.example.demo;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;
import java.util.List;

/**
 * AutoGenerator 是 MyBatis-Plus 的代码生成器
 *
 * @author Shanks
 * @date 2020-10-12
 */
public class MyBatisPlusAutoGenerator {

    private static final String PARENT_PACKAGE_NAME = "com.example.demo";
    private static final String ENTITY_PACKAGE_NAME = "model";
    private static final String AUTHOR = "Shanks";

    private static final String URL = "jdbc:mysql://localhost:3306/demo_mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8";
    private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root123456";

    private static final String TABLE_NAME = "product";

    public static void main(String[] args) {
        AutoGenerator autoGenerator = new AutoGenerator();

        /* ------------------------------ 全局配置 ------------------------------ */
        GlobalConfig globalConfig = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        // 生成文件的输出目录, 默认值: D://
        globalConfig.setOutputDir(projectPath + "/src/main/java");
        // 是否覆盖已有文件, 默认值: false
        globalConfig.setFileOverride(true);
        globalConfig.setAuthor(AUTHOR);
        // 是否打开输出目录, 默认值: true
        globalConfig.setOpen(false);
        // 是否在xml中添加二级缓存配置, 默认值: false
        globalConfig.setEnableCache(false);
        // 开启BaseResultMap, 默认值: false
        globalConfig.setBaseResultMap(true);
        // 时间类型对应策略, 默认值: DateType.TIME_PACK
        globalConfig.setDateType(DateType.ONLY_DATE);
        // 开启BaseColumnList, 默认值: false
        globalConfig.setBaseColumnList(true);
        // 开启swagger2模式, 默认值: false; 实体类无需Swagger, 一般为出入参VO类添加Swagger注释信息
        globalConfig.setSwagger2(false);
        // 设置生成的Service接口格式, 不设置的话会以IXxxService的样式
        globalConfig.setServiceName("%sService");
        globalConfig.setServiceImplName("%sServiceImpl");
        // 指定生成的主键的ID类型
        globalConfig.setIdType(IdType.AUTO);
        autoGenerator.setGlobalConfig(globalConfig);

        /* ------------------------------ 数据源配置 ------------------------------ */
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl(URL);
        dataSourceConfig.setDriverName(DRIVER_NAME);
        dataSourceConfig.setUsername(USERNAME);
        dataSourceConfig.setPassword(PASSWORD);
        dataSourceConfig.setDbType(DbType.MYSQL);
        autoGenerator.setDataSource(dataSourceConfig);

        /* ------------------------------ 包配置 ------------------------------ */
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent(PARENT_PACKAGE_NAME);
        packageConfig.setEntity(ENTITY_PACKAGE_NAME);
        autoGenerator.setPackageInfo(packageConfig);

        /* ---------- 自定义配置 ---------- */
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker, 还需要搭配autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
        // String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> fileOutConfigList = new ArrayList<>();
        // 自定义配置会被优先输出
        fileOutConfigList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名, 如果Entity设置了前后缀, 此处注意xml的名称会跟着发生变化
                return projectPath + "/src/main/resources/mapper/" + packageConfig.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        /*
        injectionConfig.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录，自定义目录用");
                if (fileType == FileType.MAPPER) {
                    // 已经生成 mapper 文件判断存在，不想重新生成返回 false
                    return !new File(filePath).exists();
                }
                // 允许生成模板文件
                return true;
            }
        });
        */
        injectionConfig.setFileOutConfigList(fileOutConfigList);
        autoGenerator.setCfg(injectionConfig);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        // 如果不想生成Controller或者Service以及ServiceImpl, 直接显式的设置为""即可
        templateConfig.setController("");
        // templateConfig.setService("");
        // templateConfig.setServiceImpl("");
        autoGenerator.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        // 采用Lombok注解
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setEntityBooleanColumnRemoveIsPrefix(true);
        strategyConfig.setRestControllerStyle(true);
        // 设置实体类属性@TableField注解, 默认为false
        strategyConfig.setEntityTableFieldAnnotationEnable(false);
        // 实体是否生成serialVersionUID, 默认值: true; 会自动生成private static final long serialVersionUID=1L;
        strategyConfig.setEntitySerialVersionUID(false);

        // 逻辑删除字段名
        // strategyConfig.setLogicDeleteFieldName("is_deleted");
        // 去掉boolean类型属性的is前缀, is_deleted --> deleted, 非Boolean类型的不会做处理
        strategyConfig.setEntityBooleanColumnRemoveIsPrefix(true);

        // 需要包含的表名
        strategyConfig.setInclude(TABLE_NAME.split(","));
        strategyConfig.setControllerMappingHyphenStyle(true);
        // 表前缀, 如t_user, 没有就注释掉此行
        // strategyConfig.setTablePrefix("t_");
        autoGenerator.setStrategy(strategyConfig);
        // 如果模板是Freemarker, 需要如下设置
        // autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
        autoGenerator.execute();
    }
}